package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstant;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private Client client;
    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void syncProductList() throws Exception {
        QueryProductListRequest request =new QueryProductListRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setCurrentPage(1);
        request.setPageSize(200);

        QueryProductListResponse response = client.queryProductList(request);
        if (!response.getBody().success){
            throw  new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }

        List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo
                = response.getBody().getData().getList().getProductInfo();

        List<ProductVo> productVoList = productInfo.stream().map(p -> {
            ProductVo productVo = BeanUtil.toBean(p, ProductVo.class);
            return productVo;
        }).collect(Collectors.toList());

        redisTemplate.opsForValue().set(CacheConstant.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(productVoList));
    }

    /**
     * 查询所有的产品
     * @return
     */
    @Override
    public List<ProductVo> allProductList() {
        //1.从redis中获取数据
        String json = redisTemplate.opsForValue().get(CacheConstant.ALL_PRODUCT_KEY);

        //2.判断json字符串是否为空 如果为空则返回一个空的集合
        if(ObjectUtil.isEmpty(json)){
            return Collections.emptyList();
        }

        //3.转换数据并返回
        List<ProductVo> productVoList = JSONUtil.toList(json, ProductVo.class);

        return productVoList;
    }

    /**
     * 新增设备
     * @param deviceDto
     */
    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //1.校验设备的名字是否使用过 如果使用 则抛出异常
        Integer count = deviceMapper.queryByDeviceName(deviceDto.getDeviceName());
        if (count>0){
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //2.新增设备到Iot平台

        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response = null;
        try {
            response = client.registerDevice(request);
        } catch (Exception e) {
            //3.校验新增是否成功 如果失败 则抛出异常 主要针对的是网络异常 超时等异常情况
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        //3.校验新增是否成功 如果失败则抛出异常 主要针对是 阿里云注册失败时响应的结果
        if (response == null||!response.getBody().success){
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        //4.判断设备的安装位置是否是老人 如果是 把physical_location_type设置为-1
        if(deviceDto.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            deviceDto.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }

        //5. 到iot平台查询设备的详细信息
        QueryProductRequest requestProduct = new QueryProductRequest();
        requestProduct.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        requestProduct.setProductKey(deviceDto.getProductKey());

        try {
            //选择TryCatch是因为如果报错的话 仍然需要程序处理 删除设备
            QueryProductResponse responseProduct = client.queryProduct(requestProduct);
            if (responseProduct == null || !responseProduct.getBody().success) {
                throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
            }else {
                //从响应结果中获取设备名称
                String productName = responseProduct.getBody().getData().getProductName();
                //6.封装数据(deviceDto,设备的详细信息)
                Device device = BeanUtil.toBean(deviceDto,Device.class);
                //补全设备id
                device.setIotId(response.getBody().getData().getIotId());
                device.setProductName(productName);
                device.setHaveEntranceGuard(0);
                //7. 调用mapper 插入设备数据
                deviceMapper.insert(device);
            }
        } catch (Exception e) {
            //8. 如果新增失败 则删除iot平台新增的设备
            DeleteDeviceRequest delRequest = new DeleteDeviceRequest();
            delRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            delRequest.setProductKey(deviceDto.getProductKey());
            delRequest.setDeviceName(deviceDto.getDeviceName());
            delRequest.setIotId(response.getBody().getData().getIotId());

            try {
                DeleteDeviceResponse deleteDeviceResponse = client.deleteDevice(delRequest);
            } catch (Exception ex) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }

        }

    }

    /**
     * 分页查询
     * @param devicePageQueryDto
     * @return
     */
    @Override
    public PageResponse<DeviceVo> queryDevicePage(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());

        Page<DeviceVo> page = deviceMapper.queryDevicePage(devicePageQueryDto);

        return PageResponse.of(page,DeviceVo.class);
    }

    /**
     * 根据Id查询设备信息
     * @param deviceDto
     * @return
     */
    @Override
    public DeviceVo queryDeviceById(DeviceDto deviceDto) {
        //查询iot平台中的设备数据
        //设置查询参数
        QueryDeviceDetailRequest request = new QueryDeviceDetailRequest();
        request.setIotId(deviceDto.getIotId());
        request.setProductKey(deviceDto.getProductKey());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryDeviceDetailResponse response;
        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        //安全校验
        if(response==null||!response.getBody().success){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }


        DeviceVo deviceVo = deviceMapper.queryDeviceById(deviceDto.getIotId());
        //解析响应结果
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();

        BeanUtil.copyProperties(data,deviceVo, CopyOptions.create().ignoreNullValue());
        return deviceVo;
    }

    /**
     * 查看物模型状态
     * @param request
     * @return
     */
    @Override
    public ResponseResult queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse response;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        return ResponseResult.success(response.getBody().getData());
    }

    /**
     * 查看指定产品的已发布物模型中的功能定义详情
     *
     * @param request 查询已发布物模型请求模型
     * @return 已发布物模型中的功能定义详情
     */
    @Override
    public ResponseResult queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        return ResponseResult.success(response.getBody().getData());
    }
}
